{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# OSMnx features demo\n",
    "\n",
    "Author: [Rui Xu]\n",
    "\n",
    "More info:\n",
    "\n",
    "  - [Documentation](https://osmnx.readthedocs.io/)\n",
    "  - [Journal article and citation info](https://geoffboeing.com/publications/osmnx-paper/)\n",
    "  - [Code repository](https://github.com/gboeing/osmnx)\n",
    "  - [Examples gallery](https://github.com/gboeing/osmnx-examples)\n",
    "  \n",
    "This notebook provides a quick tour of some of OSMnx's key features including how to:\n",
    "\n",
    "  - 下载山西地图\n",
    "  - excel读取山西太原经纬度并对齐最近点\n",
    "  - 读取山西各地市边界\n",
    "  - 作图展示保存为html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-09T07:03:51.222666600Z",
     "start_time": "2025-03-09T07:03:37.298718300Z"
    }
   },
   "outputs": [],
   "source": [
    "import networkx as nx\n",
    "import osmnx as ox\n",
    "import folium\n",
    "import geopandas as gpd"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 1. 下载山西地图并保存为G"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Administrator\\anaconda3\\envs\\ox\\Lib\\site-packages\\osmnx\\_overpass.py:267: UserWarning: This area is 73 times your configured Overpass max query area size. It will automatically be divided up into multiple sub-queries accordingly. This may take a long time.\n",
      "  multi_poly_proj = utils_geo._consolidate_subdivide_geometry(poly_proj)\n"
     ]
    }
   ],
   "source": [
    "place = \"Shanxi, China\"\n",
    "if 1:\n",
    "    G3 = ox.graph.graph_from_place(place, custom_filter='[\"highway\"~\"motorway|primary\"]') # 快\n",
    "    G32 = G3.copy()\n",
    "if 0:\n",
    "    G2 = ox.graph.graph_from_place(place, network_type=\"drive\") # 满\n",
    "    G22 = G2.copy()\n",
    "if 0:\n",
    "    fig, ax = ox.plot.plot_graph(G2)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-09T07:04:42.153000200Z",
     "start_time": "2025-03-09T07:03:51.226666Z"
    }
   },
   "execution_count": 2
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 2. excel读取山西太原经纬度"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "# 读取 Excel 文件\n",
    "file_path = 'data/shanxipoints_taiyuan.xlsx'\n",
    "df = pd.read_excel(file_path)\n",
    "df = df.dropna(subset=['经度', '纬度'])\n",
    "coordinates = list(zip(df['经度'], df['纬度']))\n",
    "supplyId = df['客户编码']\n",
    "# print(df.head())"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-09T07:08:05.445245800Z",
     "start_time": "2025-03-09T07:08:03.583871900Z"
    }
   },
   "execution_count": 5
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 3. 读取山西各地市边界"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 基于highways的地图G3作图（慢）\n",
    "G = G32.copy()\n",
    "nodes = [ox.distance.nearest_nodes(G, X=lon, Y=lat) for lon, lat in coordinates]\n",
    "geo_nodes = ox.convert.graph_to_gdfs(G, edges=False)\n",
    "orig_dest_nodes = geo_nodes.loc[nodes]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-09T07:15:33.578449400Z",
     "start_time": "2025-03-09T07:08:07.323188400Z"
    }
   },
   "execution_count": 6
  },
  {
   "cell_type": "raw",
   "source": [
    "# 4. 作图展示保存为html"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 定义山西省的主要城市\n",
    "m = orig_dest_nodes.explore(marker_kwds={\"radius\": 0.25})    \n",
    "m.save(\"data/graphShanxiTaiYuan01.html\")\n",
    "shanxi_cities = [\"Taiyuan, China\", \"Datong, China\", \"Yangquan, China\", \"Changzhi, China\",\n",
    "    \"Jincheng, China\", \"Shuozhou, China\", \"Xinzhou, China\", \"Lüliang, China\",\n",
    "    \"Jinzhong, China\", \"Linfen, China\", \"Yuncheng, China\"]\n",
    "shanxi_cities = [\"Taiyuan, China\"]\n",
    "# # 初始化地图，将中心点设在山西省附近\n",
    "# m = folium.Map(location=[37.5, 112.5], zoom_start=7, tiles=\"CartoDB positron\")\n",
    "\n",
    "# 获取每个城市的边界并绘制到地图上\n",
    "for city in shanxi_cities:\n",
    "    try:\n",
    "        gdf = ox.geocode_to_gdf(city)  # 获取城市边界\n",
    "        if not gdf.empty:\n",
    "            # 简化几何形状以减少数据量\n",
    "            sim_geo = gdf[\"geometry\"].simplify(tolerance=0.001)\n",
    "            geo_j = sim_geo.to_json()\n",
    "            geo_j = folium.GeoJson(\n",
    "                data=geo_j,\n",
    "                style_function=lambda x: {\"fillColor\": \"green\", \"color\": \"black\", \"weight\": 2, \"fillOpacity\": 0.1}\n",
    "            )\n",
    "            # 添加城市名称的弹出框\n",
    "            folium.Popup(city).add_to(geo_j)\n",
    "            geo_j.add_to(m)\n",
    "    except Exception as e:\n",
    "        print(f\"Error fetching data for {city}: {e}\")\n",
    "m.save(\"data/graphShanxiTaiYuan02_boarder.html\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-09T07:28:11.354019600Z",
     "start_time": "2025-03-09T07:28:08.226855800Z"
    }
   },
   "execution_count": 19
  }
 ],
 "metadata": {
  "kernelspec": {
   "name": "python3",
   "language": "python",
   "display_name": "Python 3 (ipykernel)"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
